#ifndef AFCORE_COMMON_LOG_LOG_
#define AFCORE_COMMON_LOG_LOG_

#include <memory>
#include <string>
#include <functional>

#include "logcommon.h"
#include "log_hub.h"
#include "logger.h"
#include "sync.h"

namespace afcore {

using namespace log;

using RDefaultFactory = SSyncFactory;

/// @brief  创建异步记录器 非阻塞
/// @tparam Appender        异步记录器类型
/// @tparam ...Args         记录器所需参数
/// @param  logger_name     记录器名称
/// @param  ...args         记录器所需参数
/// @return 异步记录器
template<typename Appender, typename... Args>
RLoggerSptr Create(std::string logger_name, Args&&... args) {
  return RDefaultFactory::Create<Appender>(std::move(logger_name), std::forward<Args>(args)...);
}

/// @brief  初始化记录器
/// @param  new_logger      记录器
AFCORE_COMMON_API
void InitializeLogger(RLoggerSptr new_logger);

/// @brief  通过记录器的名字获取记录器
/// @return 记录器
AFCORE_COMMON_API
RLoggerSptr GetLoggerByName(const std::string& logger_name);

/// @brief  设置格式器
/// @param  formatter       格式器
AFCORE_COMMON_API
void SetFormatter(RFormatterUptr formatter);

/// @brief  设置格式器模式
/// @param  pattern         格式器模式
/// @param  time_type       模式使用的时间
AFCORE_COMMON_API
void SetPattern(std::string pattern, EPatternTimeType time_type = EPatternTimeType::kPatternTimeTypeLocal);

/// @brief  设置追踪器可用
/// @param  msg_max             最大记录深度
AFCORE_COMMON_API
void EnableBacktrace(size_t msg_max);

/// @brief  设置追踪器不可用
AFCORE_COMMON_API
void DisableBacktrace();

/// @brief  转储
AFCORE_COMMON_API
void DumpBacktrace();

/// @brief  设置记录器最低日志级别
/// @param  log_level       当前记录器最低日志级别
AFCORE_COMMON_API
void SetLogLevel(ELogLevel log_level);

/// @brief  设置刷新级别
/// @param  log_level       刷新级别
AFCORE_COMMON_API
void SetFlushLevel(ELogLevel log_level);

/// @brief  指定间隔刷新所有记录器
/// @param  interval        刷新间隔
AFCORE_COMMON_API
void FlushEvery(RSeconds interval);

/// 设置错误处理
/// @param  handler         错误处理程序
AFCORE_COMMON_API
void SetErrorHander(RErrHanlder handler);

/// @brief  注册记录器
/// @param  new_logger      记录器
AFCORE_COMMON_API
void RegisterLogger(RLoggerSptr new_logger);

/// @brief  所有记录器执行函数操作
/// @param  fun             记录器要执行的操作
AFCORE_COMMON_API
void ApplyAll(const std::function<void(const RLoggerSptr)>& fun);

/// @brief  丢弃指定名称的记录器
/// @param  logger_name     要丢弃的记录器名称
AFCORE_COMMON_API
void Drop(const std::string& logger_name);

/// @brief  丢弃所有记录器
AFCORE_COMMON_API
void DropAll();

/// @brief  关闭
AFCORE_COMMON_API
void Shutdown();

/// @brief  设置自动注册标志
/// @param  automatic_registration      自动注册
AFCORE_COMMON_API
void SetAutomaticRegistration(bool automatic_registration);

/// @brief  获取默认记录器
AFCORE_COMMON_API
RLoggerSptr DefaultLogger();

/// @brief  获取默认记录器原始指针
AFCORE_COMMON_API
CLogger* DefaultLoggerRaw();

/// @brief  设置默认的记录器
/// @param  new_default_logger    新的默认记录器
void SetDefaultLogger(RLoggerSptr new_default_logger);

/// @brief  记录日志
/// @tparam ...Args     额外参数
/// @param  src_info    源文件信息
/// @param  l           日志级别
/// @param  fmt         格式化字符串
/// @param  ...args     额外参数
template<typename... Args>
void Log(SSrcLocInfo src_info, afcore::log::ELogLevel l, RStringView fmt, const Args&... args) {
  DefaultLoggerRaw()->Log(src_info, l, fmt, args...);
}

template<typename... Args>
void Log(ELogLevel l, RStringView fmt, const Args&... args) {
  DefaultLoggerRaw()->Log(SSrcLocInfo{}, l, fmt, args...);
}

template<typename... Args>
void Trace(RStringView fmt, const Args&... args) {
  DefaultLoggerRaw()->Trace(fmt, args...);
}

template<typename... Args>
void Debug(RStringView fmt, const Args&... args) {
  DefaultLoggerRaw()->Debug(fmt, args...);
}

template<typename... Args>
void Info(RStringView fmt, const Args&... args) {
  DefaultLoggerRaw()->Info(fmt, args...);
}

template<typename... Args>
void Warn(RStringView fmt, const Args&... args) {
  DefaultLoggerRaw()->Warn(fmt, args...);
}

template<typename... Args>
void Error(RStringView fmt, const Args&... args) {
  DefaultLoggerRaw()->Error(fmt, args...);
}

template<typename... Args>
void Fatal(RStringView fmt, const Args&... args) {
  DefaultLoggerRaw()->Fatal(fmt, args...);
}

template<typename T>
void Log(SSrcLocInfo src_info, ELogLevel l, const T& msg) {
  DefaultLoggerRaw()->Log(src_info, l, msg);
}

template<typename T>
void Log(ELogLevel l, const T& msg) {
  DefaultLoggerRaw()->Log(l, msg);
}

template<typename T>
void Trace(const T& msg) {
  DefaultLoggerRaw()->Trace(msg);
}

template<typename T>
void Debug(const T& msg) {
  DefaultLoggerRaw()->Debug(msg);
}

template<typename T>
void Info(const T& msg) {
  DefaultLoggerRaw()->Info(msg);
}

template<typename T>
void Warn(const T& msg) {
  DefaultLoggerRaw()->Warn(msg);
}

template<typename T>
void Error(const T& msg) {
  DefaultLoggerRaw()->Error(msg);
}

template<typename T>
void Fatal(const T& msg) {
  DefaultLoggerRaw()->Fatal(msg);
}

} // !namespace afcore

#if AFCORE_PLATFORM != AFCORE_PLATFORM_WIN
void CheckArgs(const char*, ...) AFCORE_AF_PRINTF(1, 2);
void CheckArgs(const std::string&, ...);

#define LOGGER_CALL(logger, level, ...)                                                             \
  do {                                                                                              \
    if (AFCORE_FORMAT_CHECK)                                                                        \
      CheckArgs(__VA_ARGS__);                                                                       \
    (logger)->Log(afcore::log::SSrcLocInfo{__FILE__, __LINE__, __FUNCTION__}, level, __VA_ARGS__);  \
  } while(0)
#else
#define LOGGER_CALL(logger, level, ...)                                                             \
  (logger)->Log(afcore::log::SSrcLocInfo{__FILE__, __LINE__, __FUNCTION__}, level, __VA_ARGS__)
//  __pragma(warning(push))                                                                           \
//  __pragma(warning(disable:4127))                                                                   \
//  do {                                                                                              \
//    (logger)->Log(afcore::log::SSrcLocInfo{__FILE__, __LINE__, __FUNCTION__}, level, __VA_ARGS__);  \
//  } while(0)                                                                                        \
//  __pragma(warning(pop))
#endif

#define LOGGER_TRACE(logger, ...) LOGGER_CALL(logger, afcore::log::kLogLevelTrace, __VA_ARGS__)
#define LOGGER_DEBUG(logger, ...) LOGGER_CALL(logger, afcore::log::kLogLevelDebug, __VA_ARGS__)
#define LOGGER_INFO(logger, ...) LOGGER_CALL(logger, afcore::log::kLogLevelInfo, __VA_ARGS__)
#define LOGGER_WARN(logger, ...) LOGGER_CALL(logger, afcore::log::kLogLevelWarn, __VA_ARGS__)
#define LOGGER_ERROR(logger, ...) LOGGER_CALL(logger, afcore::log::kLogLevelError, __VA_ARGS__)
#define LOGGER_FATAL(logger, ...) LOGGER_CALL(logger, afcore::log::kLogLevelFatal, __VA_ARGS__)

/// @brief  日志 级别 trace
#define LOG_TRACE(...) LOGGER_TRACE(afcore::DefaultLoggerRaw(), __VA_ARGS__)
/// @brief  日志 级别 debug
#define LOG_DEBUG(...) LOGGER_DEBUG(afcore::DefaultLoggerRaw(), __VA_ARGS__)
/// @brief  日志 级别 info
#define LOG_INFO(...) LOGGER_INFO(afcore::DefaultLoggerRaw(), __VA_ARGS__)
/// @brief  日志 级别 warn
#define LOG_WARN(...) LOGGER_WARN(afcore::DefaultLoggerRaw(), __VA_ARGS__)
/// @brief  日志 级别 error
#define LOG_ERROR(...) LOGGER_ERROR(afcore::DefaultLoggerRaw(), __VA_ARGS__)
/// @brief  日志 级别 fatal
#define LOG_FATAL(...) LOGGER_FATAL(afcore::DefaultLoggerRaw(), __VA_ARGS__)

#endif //! AFCORE_COMMON_LOG_LOG_